#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <stdint.h>
#include "../common_defs.h"
#include "parser.h"

// 保存当前正在处理的函数名
char* current_func_name = NULL;


// 提前声明parse_program函数
void parse_program();

void expression(int level) {
    // expressions have various format.
    // but majorly can be divided into two parts: unit and operator
    // for example `(char) *a[10] = (int *) func(b > 0 ? 10 : 20);
    // `a[10]` is an unit while `*` is an operator.
    // `func(...)` in total is an unit.
    // so we should first parse those unit and unary operators
    // and then the binary ones
    //
    // also the expression can be in the following types:
    //
    // 1. unit_unary ::= unit | unit unary_op | unary_op unit
    // 2. expr ::= unit_unary (bin_op unit_unary ...)

    // unit_unary()
    Symbol* id_sym;
    SymInfo* id_info;
    int tmp;
    intptr_t *addr;
    {
        if (!token) {
            printf("%d: unexpected token EOF of expression\n", line);
            exit(-1);
        }
        if (token == Num) {
            match(Num);

            // emit code
            *++text = IMM;
            *++text = token_val;
            expr_type = INT; // 因为对于数字只支持整数
        }
        else if (token == Str) {
            // continous string "abc" "abc"

            // emit code
            *++text = IMM;
            *++text = token_val;  // token_val在next分析当中获取，可以以是字符串的起始地址

            match(Str);
            // store the rest strings
            while (token == Str) {
                match(Str);
            }

            // 注意因为match的时候已经做了64字节对齐，所以这里不需要再重复做
            //data = (char *)(((intptr_t)data + 64) & (-64)); 
            expr_type = PTR;
        }
        else if (token == Sizeof) {
            // sizeof is actually an unary operator
            // now only `sizeof(int)`, `sizeof(char)` and `sizeof(*...)` are
            // supported.
            match(Sizeof);
            match('(');
            expr_type = INT;

            if (token == Int) {
                match(Int);
            } else if (token == Char) {
                match(Char);
                expr_type = CHAR;
            }

            while (token == Mul) {
                match(Mul);
                expr_type = expr_type + PTR;
            }

            match(')');

            // emit code
            *++text = IMM;
            *++text = (expr_type == CHAR) ? sizeof(char) : sizeof(intptr_t);

            expr_type = INT;
        }
        else if (token == Id) {
            // there are several type when occurs to Id
            // but this is unit, so it can only be
            // 1. function call 调用其他函数
            // 2. Enum variable
            // 3. global/local variable
            
            // 保存当前标识符名称，因为match后token_buffer会更新
            char* id_name = strdup(token_buffer);
            
            match(Id);

            // 查找符号表
            id_sym = find_symbol_all(scope_stack, id_name);
            
            if (!id_sym) {
                printf("%d: undefined symbol %s\n", line, id_name);
                exit(-1);
            }
            
            id_info = id_sym->info;

            if (token == '(') {
                // function call
                match('(');

                // pass in arguments
                tmp = 0; // number of arguments
                while (token != ')') {
                    expression(Assign); // 检测到是函数准备入参，用低优先级assign保证函数参数能够正确识别比如func(a + b * c)
                    *++text = PUSH;
                    tmp ++;

                    if (token == ',') {
                        match(',');
                    }
                }
                match(')');

                // emit code
                if (id_info->sym_class == SYM_SYSTEM) {
                    // system functions
                    *++text = id_info->addr;
                }
                else if (id_info->sym_class == SYM_FUNCTION) {
                    // function call
                    *++text = CALL;
                    *++text = id_info->addr;
                }
                else {
                    printf("%d: bad function call\n", line);
                    exit(-1);
                }

                // clean the stack for arguments
                if (tmp > 0) {
                    *++text = ADJ;
                    *++text = tmp;
                }
                
                // 设置表达式类型
                int base_type = INT;
                if (id_info->is_pointer >= 1) {
                    if(id_info->data_type == TYPE_PTR_INT)
                        base_type = INT + id_info->is_pointer * PTR;
                    else if(id_info->data_type == TYPE_PTR_CHAR)
                        base_type = CHAR + id_info->is_pointer * PTR;
                }
                else{
                    if(id_info->data_type == TYPE_INT){
                        base_type = INT;
                    }
                    else if(id_info->data_type == TYPE_CHAR){
                        base_type = CHAR;
                    }
                }                
                expr_type = base_type;               
                
            }
            else if (id_info->sym_class == SYM_ENUM) { // 识别枚举变量
                // enum variable
                *++text = IMM;
                *++text = id_info->addr;
                expr_type = INT;
            }
            else {
                // variable
                if (id_info->sym_class == SYM_LOCAL) {
                    *++text = LEA;
                    *++text = index_of_bp - id_info->addr;  // 局部变量：负偏移
                }
                else if (id_info->sym_class == SYM_PARAM) {
                    *++text = LEA;
                    *++text = index_of_bp - id_info->addr;  // 参数：正偏移
                }
                else if (id_info->sym_class == SYM_GLOBAL) {
                    *++text = IMM;
                    *++text = id_info->addr;
                }
                else {
                    printf("%d: undefined variable\n", line);
                    exit(-1);
                }

                // emit code, default behaviour is to load the value of the
                // address which is stored in `ax`
                
                // 设置表达式类型
                int base_type = INT;
                if (id_info->is_pointer >= 1) {
                    if(id_info->data_type == TYPE_PTR_INT)
                        base_type = INT + id_info->is_pointer * PTR;
                    else if(id_info->data_type == TYPE_PTR_CHAR)
                        base_type = CHAR + id_info->is_pointer * PTR;
                }
                else{
                    if(id_info->data_type == TYPE_INT){
                        base_type = INT;
                    }
                    else if(id_info->data_type == TYPE_CHAR){
                        base_type = CHAR;
                    }
                }
                
                expr_type = base_type;
                
                *++text = (expr_type == CHAR) ? LC : LI;
            }
        }
        else if (token == '(') {
            // cast or parenthesis 强转
            match('(');
            if (token == Int || token == Char) {
                tmp = (token == Char) ? CHAR : INT; // cast type
                match(token);
                while (token == Mul) {
                    match(Mul);
                    tmp = tmp + PTR;
                }

                match(')');

                expression(Inc); // cast has precedence as Inc(++)

                expr_type  = tmp; // 转换类型
            } else {
                // normal parenthesis
                expression(Assign);
                match(')');
            }
        }
        else if (token == Mul) {
            // dereference *<addr>
            match(Mul);
            expression(Inc); // dereference has the same precedence as Inc(++)

            if (expr_type >= PTR) {
                expr_type = expr_type - PTR;
            } else {
                printf("%d: bad dereference\n", line);
                exit(-1);
            }

            *++text = (expr_type == CHAR) ? LC : LI;
        }
        else if (token == And) {
            // get the address of
            match(And);
            expression(Inc); // get the address of
            if (*text == LC || *text == LI) {
                text --;
            } else {
                printf("%d: bad address of\n", line);
                exit(-1);
            }

            expr_type = expr_type + PTR;
        }
        else if (token == '!') {
            // not
            match('!');
            expression(Inc);

            // emit code, use <expr> == 0
            *++text = PUSH;
            *++text = IMM;
            *++text = 0;
            *++text = EQ;

            expr_type = INT;
        }
        else if (token == '~') {
            // bitwise not
            match('~');
            expression(Inc);

            // emit code, use <expr> XOR -1
            *++text = PUSH;
            *++text = IMM;
            *++text = -1;
            *++text = XOR;

            expr_type = INT;
        }
        else if (token == Add) {
            // +var, do nothing
            match(Add);
            expression(Inc);

            expr_type = INT;
        }
        else if (token == Sub) {
            // -var
            match(Sub);

            if (token == Num) {
                *++text = IMM;
                *++text = -token_val;
                match(Num);
            } else {

                *++text = IMM;
                *++text = -1;
                *++text = PUSH;
                expression(Inc);
                *++text = MUL;
            }

            expr_type = INT;
        }
        else if (token == Inc || token == Dec) {
            tmp = token;
            match(token);
            expression(Inc);
            if (*text == LC) {
                *text = PUSH;  // to duplicate the address
                *++text = LC;
            } else if (*text == LI) {
                *text = PUSH;
                *++text = LI;
            } else {
                printf("%d: bad lvalue of pre-increment\n", line);
                exit(-1);
            }
            *++text = PUSH;
            *++text = IMM;
            *++text = (expr_type > PTR) ? sizeof(intptr_t) : sizeof(char);
            *++text = (tmp == Inc) ? ADD : SUB;
            *++text = (expr_type == CHAR) ? SC : SI;
        }
        else {
            printf("%d: bad expression\n", line);
            exit(-1);
        }
    }

    // binary operator and postfix operators.
    // 处理二元运算符和单目运算符
    {
        while (token >= level) {
            // handle according to current operator's precedence
            tmp = expr_type;
            if (token == Assign) {
                // var = expr;
                match(Assign);
                if (*text == LC || *text == LI) {
                    *text = PUSH; // save the lvalue's pointer
                } else {
                    printf("%d: bad lvalue in assignment\n", line);
                    exit(-1);
                }
                expression(Assign); // 继续分析表达式的右值表达式

                expr_type = tmp;
                *++text = (expr_type == CHAR) ? SC : SI; // 最后将右值使用SI为变量赋值
            }
            else if (token == Cond) {
                // expr ? a : b;
                match(Cond);
                *++text = JZ;
                addr = ++text;
                expression(Assign);
                if (token == ':') {
                    match(':');
                } else {
                    printf("%d: missing colon in conditional\n", line);
                    exit(-1);
                }
                *addr = (intptr_t)(text + 3);
                *++text = JMP;
                addr = ++text;
                expression(Cond);
                *addr = (intptr_t)(text + 1);
            }
            else if (token == Lor) {
                // logic or,s比如 2 || 0，第一个操作数为2则返回2，否则返回第二个操作数
                match(Lor);
                *++text = JNZ;
                addr = ++text;
                expression(Lan);
                *addr = (intptr_t)(text + 1);
                expr_type = INT;
            }
            else if (token == Lan) {
                // logic and
                match(Lan);
                *++text = JZ;
                addr = ++text;
                expression(Or);
                *addr = (intptr_t)(text + 1);
                expr_type = INT;
            }
            else if (token == Or) {
                // bitwise or
                match(Or);
                *++text = PUSH;
                expression(Xor);
                *++text = OR;
                expr_type = INT;
            }
            else if (token == Xor) {
                // bitwise xor
                match(Xor);
                *++text = PUSH;
                expression(And);
                *++text = XOR;
                expr_type = INT;
            }
            else if (token == And) {
                // bitwise and
                match(And);
                *++text = PUSH;
                expression(Eq);
                *++text = AND;
                expr_type = INT;
            }
            else if (token == Eq) {
                // equal ==
                match(Eq);
                *++text = PUSH;
                expression(Ne);
                *++text = EQ;
                expr_type = INT;
            }
            else if (token == Ne) {
                // not equal !=
                match(Ne);
                *++text = PUSH;
                expression(Lt);
                *++text = NE;
                expr_type = INT;
            }
            else if (token == Lt) {
                // less than
                match(Lt);
                *++text = PUSH;
                expression(Shl);
                *++text = LT;
                expr_type = INT;
            }
            else if (token == Gt) {
                // greater than
                match(Gt);
                *++text = PUSH;
                expression(Shl);
                *++text = GT;
                expr_type = INT;
            }
            else if (token == Le) {
                // less than or equal to
                match(Le);
                *++text = PUSH;
                expression(Shl);
                *++text = LE;
                expr_type = INT;
            }
            else if (token == Ge) {
                // greater than or equal to
                match(Ge);
                *++text = PUSH;
                expression(Shl);
                *++text = GE;
                expr_type = INT;
            }
            else if (token == Shl) {
                // shift left
                match(Shl);
                *++text = PUSH;
                expression(Add);
                *++text = SHL;
                expr_type = INT;
            }
            else if (token == Shr) {
                // shift right
                match(Shr);
                *++text = PUSH;
                expression(Add);
                *++text = SHR;
                expr_type = INT;
            }
            else if (token == Add) {
                // add
                match(Add);
                *++text = PUSH;
                expression(Mul);

                expr_type = tmp;
                if (expr_type > PTR) {
                    // pointer type, and not `char *`
                    *++text = PUSH;
                    *++text = IMM;
                    *++text = sizeof(intptr_t);
                    *++text = MUL;
                }
                *++text = ADD;
            }
            else if (token == Sub) {
                // sub
                match(Sub);
                *++text = PUSH;
                expression(Mul);
                if (tmp > PTR && tmp == expr_type) {
                    // pointer subtraction 指针相减
                    *++text = SUB;
                    *++text = PUSH;
                    *++text = IMM;
                    *++text = sizeof(intptr_t);
                    *++text = DIV;
                    expr_type = INT;
                } else if (tmp > PTR) {
                    // pointer movement  指针加一个整数进行地址偏移
                    *++text = PUSH;
                    *++text = IMM;
                    *++text = sizeof(intptr_t);
                    *++text = MUL;
                    *++text = SUB;
                    expr_type = tmp;
                } else {
                    // numeral subtraction
                    *++text = SUB;
                    expr_type = tmp;
                }
            }
            else if (token == Mul) {
                // multiply
                match(Mul);
                *++text = PUSH;
                expression(Inc);
                *++text = MUL;
                expr_type = tmp;
            }
            else if (token == Div) {
                // divide
                match(Div);
                *++text = PUSH;
                expression(Inc);
                *++text = DIV;
                expr_type = tmp;
            }
            else if (token == Mod) {
                // Modulo
                match(Mod);
                *++text = PUSH;
                expression(Inc);
                *++text = MOD;
                expr_type = tmp;
            }
            else if (token == Inc || token == Dec) {
                // postfix inc(++) and dec(--)
                // we will increase the value to the variable and decrease it
                // on `ax` to get its original value.
                if (*text == LI) {
                    *text = PUSH;
                    *++text = LI;
                }
                else if (*text == LC) {
                    *text = PUSH;
                    *++text = LC;
                }
                else {
                    printf("%d: bad value in increment\n", line);
                    exit(-1);
                }

                *++text = PUSH;
                *++text = IMM;
                *++text = (expr_type > PTR) ? sizeof(intptr_t) : sizeof(char);
                *++text = (token == Inc) ? ADD : SUB;
                *++text = (expr_type == CHAR) ? SC : SI;
                *++text = PUSH;
                *++text = IMM;
                *++text = (expr_type > PTR) ? sizeof(intptr_t) : sizeof(char);
                *++text = (token == Inc) ? SUB : ADD;
                match(token);
            }
            else if (token == Brak) {
                // array access var[xx]
                match(Brak);
                *++text = PUSH; // 左值入栈
                expression(Assign);
                match(']');

                if (tmp > PTR) {
                    // pointer, `not char *`
                    *++text = PUSH;
                    *++text = IMM;
                    *++text = sizeof(intptr_t);
                    *++text = MUL;
                }
                else if (tmp < PTR) {
                    printf("%d: pointer type expected\n", line);
                    exit(-1);
                }
                expr_type = tmp - PTR;
                *++text = ADD;
                *++text = (expr_type == CHAR) ? LC : LI;
            }
            else {
                printf("%d: compiler error, token = %d\n", line, token);
                exit(-1);
            }
        }
    }
}

void statement() {
    // there are 6 kinds of statements here:
    // 1. if (...) <statement> [else <statement>]
    // 2. while (...) <statement>
    // 3. { <statement> }
    // 4. return xxx;
    // 5. <empty statement>;
    // 6. expression; (expression end with semicolon)

    intptr_t *a, *b, *c, *d, *e; // bess for branch control

    if (token == If) {
        // if (...) <statement> [else <statement>]
        //
        //   if (...)           <cond>
        //                      JZ a
        //     <statement>      <statement>
        //   else:              JMP b
        // a:                 a:
        //     <statement>      <statement>
        // b:                 b:
        //
        //
        match(If);
        match('(');
        expression(Assign);  // parse condition
        match(')');

        // emit code for if
        *++text = JZ;
        b = ++text;

        statement();         // parse statement
        if (token == Else) { // parse else
            match(Else);

            // emit code for JMP B
            *b = (intptr_t)(text + 3);
            *++text = JMP;
            b = ++text;

            statement();
        }

        *b = (intptr_t)(text + 1);
    }
    else if (token == While) {
        //
        // a:                     a:
        //    while (<cond>)        <cond>
        //                          JZ b
        //     <statement>          <statement>
        //                          JMP a
        // b:                     b:
        match(While);

        a = text + 1;

        match('(');
        expression(Assign);
        match(')');

        *++text = JZ;
        b = ++text;

        statement();

        *++text = JMP;
        *++text = (intptr_t)a;
        *b = (intptr_t)(text + 1);
    }
    else if (token == For){
        /*
            标准for循环优化结构:
            for(<init>; <cond>; <iter>) {    <init>
                <statement>                  a: <cond>
            }                                   JZ b
                                                <statement>
                                                <iter>
                                                JMP a (已包含在迭代表达式中)
                                             b:
        */
       // a：记录条件判断开始位置
       // b：记录条件为假时跳转位置
       // c：记录循环体语句开始位置
       // d：记录迭代表达式开始位置
       // e：记录for循环体结束位置
        match(For);

        match('(');
        expression(Assign);  // 初始化表达式
        match(';');

        a = text + 1;        // 条件表达式开始位置
        expression(Assign);  // 条件表达式
        *++text = JZ;        // 条件为假时跳转
        b = ++text;          // 记录跳转地址位置
        d = text + 1;        // 记录迭代表达式开始位置
        
        match(';');
        expression(Assign);  // 迭代表达式
        *++text = JMP;       // 跳回条件判断 (这里已经添加了跳转指令)
        *++text = (intptr_t)a;
        c = text + 1;        // 记录循环体语句开始位置
        match(')');

        statement();         // 循环体语句

        e = text + 1;        // 循环结束位置
        *b = (intptr_t)e;    // 设置条件为假时跳转到循环结束
        
        // 计算迭代表达式长度（指针数量）
        int iterator_len = c - d;
        if (iterator_len <= 0) {
            // 如果没有迭代表达式，直接完成
            return;
        }
        
        // 分配临时空间保存迭代表达式
        intptr_t *tmp = (intptr_t *)malloc(sizeof(intptr_t) * iterator_len);
        if (!tmp) {
            printf("%d: memory allocation failed\n", line);
            exit(-1);
        }
        memcpy(tmp, d, iterator_len * sizeof(intptr_t));

        // 计算循环体语句长度
        int statment_len = e - c;    
        // 将循环体语句移到迭代表达式位置，比memcpy更安全，避免了内存重叠时的复制覆盖
        memmove(d, c, statment_len * sizeof(intptr_t));
        
        // 计算新的位置
        intptr_t *statment_end = d + statment_len;
        
        // 将迭代表达式复制到循环体语句后面
        memcpy(statment_end, tmp, iterator_len * sizeof(intptr_t));
        
        // 注意：不需要再次添加跳回条件判断的指令，因为这已经包含在复制的迭代表达式中
        // 更新text指针位置
        text = statment_end + iterator_len - 1;
        
        // 释放临时空间
        free(tmp);
    }
    else if (token == Enum) {
        // enum [id] { a = 10, b = 20, ... }
        match(Enum); // match 函数比较当前token，取出下一个token
        if (token != '{') {
            match(Id); // skip the [id] part
        }
        if (token == '{') {
            // parse the assign part
            match('{');
            enum_declaration();
            match('}');
        }

        match(';');
    }
    else if (token == '{') {
        // { <statement> }
        match('{');
        
        // 创建新的块作用域
        push_scope(scope_stack);
        
        // 创建一个SYM_BLOCK符号来关联这个作用域
        Scope* block_scope = current_scope(scope_stack);
        Scope* parent_scope = block_scope->parent;
        
        if (parent_scope) {
            // 生成唯一的块名称
            static int block_counter = 0;
            char block_name[32];
            snprintf(block_name, sizeof(block_name), "__block_%d", block_counter++);
            
            // 创建块符号信息
            SymInfo* block_info = create_symbol_info(block_name, INT, Block, 0);
            block_info->sym_class = SYM_BLOCK;
            block_info->func_scope = block_scope;  // 关联块作用域
            
            // 将块符号添加到父作用域
            add_symbol(parent_scope, block_name, block_info);
        }

        while (token != '}') {
            statement();
        }
        
        // 退出块作用域
        pop_scope(scope_stack);

        match('}');
    }
    else if (token == Return) {
        // return [expression];
        match(Return);

        if (token != ';') {
            expression(Assign);
        }

        match(';');

        // emit code for return
        *++text = LEV;
    }
    else if (token == ';') {
        // empty statement
        match(';');
    }
    else {
        // a = b; or function_call();
        expression(Assign);
        match(';');
    }
}

void function_parameter() {
    int type;
    int params;
    params = 0;
    
    // 创建函数参数作用域
    push_scope(scope_stack);
    
    // 获取父作用域中的函数符号
    Scope* parent = current_scope(scope_stack)->parent;
    Symbol* func_sym = NULL;
    
    // 在全局作用域中查找最近声明的函数
    if (parent) {
        // 使用当前处理的函数名查找函数符号
        if (current_func_name) {
            func_sym = find_symbol_current(parent, current_func_name);
        }
    }
    
    while (token != ')') {
        // int name, ...
        type = INT;
        if (token == Int) {
            match(Int);
        } else if (token == Char) {
            type = CHAR;
            match(Char);
        }

        // pointer type
        while (token == Mul) {
            match(Mul);
            type = type + PTR;
        }

        // parameter name
        if (token != Id) {
            printf("%d: bad parameter declaration\n", line);
            exit(-1);
        }
        
        // 检查是否已经在当前作用域声明
        Scope* current = current_scope(scope_stack);
        Symbol* sym = find_symbol_current(current, token_buffer);
        if (sym) {
            printf("%d: duplicate parameter declaration\n", line);
            exit(-1);
        }

        // 保存当前参数名，因为match后token_buffer会更新
        char* param_name = strdup(token_buffer);

        match(Id);
        
        // 创建参数符号信息，参数在栈中的位置是bp + 2 + params
        // 因为bp+0是旧bp，bp+1是返回地址，bp+2开始是参数
        SymInfo* param_info = create_symbol_info(param_name, type, Para, params);
        param_info->sym_class = SYM_PARAM;
        
        if (func_sym && func_sym->info->sym_class == SYM_FUNCTION) {
            SymInfo* func_info = func_sym->info;
            
            // 创建参数链表节点
            Param* param = (Param*)malloc(sizeof(Param));
            param->type = param_info->data_type;
            param->name = param_info->name;
            param->offset = param_info->addr;  // 已经是正确的bp偏移量
            param->next = NULL;
            
            // 添加到参数链表
            if (!func_info->params) {
                func_info->params = param;
            } else {
                // 添加到链表末尾
                Param* last = func_info->params;
                while (last->next) last = last->next;
                last->next = param;
            }
            
            func_info->param_count++;
        }
        
        // 添加参数到当前作用域
        Scope* current_param_scope = current_scope(scope_stack);
        add_symbol(current_param_scope, param_info->name, param_info);
        
        // 释放临时参数名
        free(param_name);
        
        params++;

        if (token == ',') {
            match(',');
        }
    }
    
    index_of_bp = params+1; // 预留一个返回地址位置，因为如果函数被调用需要将下一条指令的位置保存在栈中以便函数结束时重新定位pc的值。
}

void function_body() {
    // type func_name (...) {...}
    //                   -->|   |<--

    // ... {
    // 1. local declarations
    // 2. statements
    // }
    int pos_local; // position of local variables on the stack.
    int type;
    pos_local = index_of_bp; // 定位局部变量的起始偏移
    
    // 创建函数体作用域（与参数作用域相同）
    Scope* func_scope = current_scope(scope_stack);
    
    // 获取函数符号，关联函数体作用域
    Symbol* func_sym = NULL;
    Scope* parent = func_scope->parent;
    
    // 使用current_func_name直接查找函数符号
    if (parent && current_func_name) {
        func_sym = find_symbol_current(parent, current_func_name);
    }

    // 将函数的作用域和其符号表关联起来，以便函数可以通过符号表的func_scope查找其父作用域
    if (func_sym && func_sym->info->sym_class == SYM_FUNCTION) {
        func_sym->info->func_scope = func_scope;
    }

    while (token == Int || token == Char) { // variable_decl, 处理局部变量声明
        // local variable declaration, just like global ones.
        basetype = (token == Int) ? INT : CHAR;
        match(token);

        while (token != ';') {
            type = basetype;
            while (token == Mul) {
                match(Mul);
                type = type + PTR;
            }

            if (token != Id) {
                // invalid declaration
                printf("%d: bad local declaration\n", line);
                exit(-1);
            }
            
            // 检查是否已经在当前作用域声明
            Scope* current = current_scope(scope_stack);
            Symbol* sym = find_symbol_current(current, token_buffer);
            if (sym) {
                printf("%d: duplicate local declaration\n", line);
                exit(-1);
            }
            
            // 保存当前标识符名称，因为match后token_buffer会更新
            char* var_name = strdup(token_buffer);
            
            match(Id);
            
            // 创建局部变量符号信息
            SymInfo* local_info = create_symbol_info(var_name, type, Loc, ++pos_local);
            local_info->sym_class = SYM_LOCAL;
            
            // 检查是否有初始值
            if (token == Assign) {
                match(Assign);
                if (token == Str) {
                    local_info->dvalue.ptr_val = (intptr_t)token_val;
                    local_info->is_init = 1;
                    match(Str);
                }
                else {
                    local_info->dvalue.int_val = token_val;
                    local_info->is_init = 1;
                    match(Num);
                }
            }
            
            // 添加局部变量到当前作用域
            Scope* current_local_scope = current_scope(scope_stack);
            add_symbol(current_local_scope, local_info->name, local_info);
            
            // 释放临时变量名
            free(var_name);
            
            if (token == ',') {
                match(',');
            }
        }
        match(';');
    }

    // save the stack size for local variables
    *++text = ENT; 
    *++text = pos_local - index_of_bp; // 为局部变量分配空间

    // 遍历局部变量并生成初始化代码
    Scope* scope = current_scope(scope_stack);
    for (int i = 0; i < HASH_SIZE; i++) {
        Symbol* sym = scope->hash_table[i];
        while (sym) {
            SymInfo* info = sym->info;
            // 如果是局部变量且有初始值
            if (info->sym_class == SYM_LOCAL && 
                (info->is_init == 1)) {
                
                // 生成初始化代码
                *++text = LEA;
                *++text = index_of_bp - info->addr;
                *++text = PUSH;
                *++text = IMM;
                
                if (info->data_type == TYPE_CHAR || info->data_type == TYPE_PTR_CHAR)
                    *++text = (intptr_t)info->dvalue.ptr_val;
                else
                    *++text = info->dvalue.int_val;
                    
                *++text = (info->data_type == TYPE_CHAR) ? SC : SI;
            }
            sym = sym->next;
        }
    }

    // statements
    while (token != '}') {
        statement();
    }

    // emit code for leaving the sub function
    *++text = LEV;
    
    // 返回到函数参数作用域的父作用域（通常是全局作用域）
    pop_scope(scope_stack);
}

void function_declaration() {
    // type func_name (...) {...}
    //               | this part

    match('(');
    function_parameter();
    match(')');
    match('{');
    function_body();

}

void enum_declaration() {
    // parse enum [id] { a = 1, b = 3, ...}
    int i;
    i = 0;
    
    while (token != '}') {
        if (token != Id) {
            printf("%d: bad enum identifier %d\n", line, token);
            exit(-1);
        }
        
        // 保存枚举名
        char* enum_name = strdup(token_buffer);
        
        next();
        if (token == Assign) {
            // like {a=10}
            next();
            if (token != Num) {
                printf("%d: bad enum initializer\n", line);
                exit(-1);
            }
            i = token_val;
            next();
        }

        // 创建并添加枚举常量到当前作用域
        SymInfo* enum_info = create_symbol_info(enum_name, INT, Enum, i);
        enum_info->sym_class = SYM_ENUM; // 枚举常量视为枚举变量, 变量类型为INT
        enum_info->dvalue.int_val = i++;
        
        Scope* current_enum_scope = current_scope(scope_stack);
        add_symbol(current_enum_scope, enum_name, enum_info);
        
        free(enum_name); // 释放临时字符串

        if (token == ',') {
            next();
        }
    }
}

void global_declaration() {
    // global_declaration ::= enum_decl | variable_decl | function_decl
    //
    // enum_decl ::= 'enum' [id] '{' id ['=' 'num'] {',' id ['=' 'num'} '}'
    //
    // variable_decl ::= type {'*'} id { ',' {'*'} id } ';'
    //
    // function_decl ::= type {'*'} id '(' parameter_decl ')' '{' body_decl '}'

    int type; // tmp, actual type for variable
    
    basetype = INT;

    // parse enum, this should be treated alone.
    if (token == Enum) {
        // enum [id] { a = 10, b = 20, ... }
        match(Enum); // match 函数比较当前token，取出下一个token
        if (token != '{') {
            match(Id); // skip the [id] part
        }
        if (token == '{') {
            // parse the assign part
            match('{');
            enum_declaration();
            match('}');
        }

        match(';');
        return;
    }

    // parse type information
    if (token == Int) {
        match(Int);
    }
    else if (token == Char) {
        match(Char);
        basetype = CHAR;
    }

    // parse the comma seperated variable declaration.
    while (token != ';' && token != '}') {
        type = basetype;
        // parse pointer type, note that there may exist `int ****x;`
        while (token == Mul) {
            match(Mul);
            type = type + PTR;
        }

        if (token != Id) {
            // invalid declaration
            printf("%d: bad global declaration\n", line);
            exit(-1);
        }
        
        // 保存当前标识符名称
        char *name = strdup(token_buffer);
        
        // 获取当前作用域
        Scope* current = current_scope(scope_stack);
        // 检查标识符是否已经存在
        Symbol* sym = find_symbol_current(current, name);
        
        // 检查是否存在重复声明
        if (sym) {
            printf("%d: duplicate global declaration\n", line);
            exit(-1);
        }
        
        match(Id);
        
        if (token == '(') { // 函数声明
            // 创建函数符号信息
            if(strcmp("main", name) == 0){
                idmain = text + 1;
            }
            SymInfo* func_info = create_symbol_info(name, type, Fun, (intptr_t)(text + 1));
            func_info->sym_class = SYM_FUNCTION;
            
            // 添加函数到全局作用域
            Scope* current_func_scope = current_scope(scope_stack);
            add_symbol(current_func_scope, name, func_info);
            
            // 保存当前处理的函数名
            if (current_func_name) {
                free(current_func_name);
            }
            current_func_name = strdup(name);
            
            // 处理函数声明
            function_declaration();
        } else {
            // 变量声明
            SymInfo* var_info = create_symbol_info(name, type, Glo, (intptr_t)data);
            var_info->sym_class = SYM_GLOBAL;
            
            // 调整data指针，64位对齐
            data = (char *)(((intptr_t)data + 64) & (-64));
            
            // 检查初始化
            if (token == Assign) {
                match(Assign);
                var_info->is_init = 1;
                if (token == Str) {
                    var_info->dvalue.ptr_val = token_val;
                    // 初始化全局变量
                    *(intptr_t *)var_info->addr = token_val;
                    match(Str);
                }
                else if(token == Num){
                    var_info->dvalue.int_val = token_val;
                    // 初始化全局变量
                    *(intptr_t *)var_info->addr = token_val;
                    match(Num);
                }
                else{ // 是枚举变量
                    char *name = strdup(token_buffer);
                    Scope* current = current_scope(scope_stack);
                    // 检查标识符是否已经存在
                    Symbol* sym = find_symbol_current(current, name);
                    if (!sym) {
                        printf("%d: undefined symbol\n", line);
                        exit(-1);
                    }
                    var_info->dvalue.ptr_val = sym->info->dvalue.int_val;
                    *(intptr_t *)var_info->addr = sym->info->dvalue.int_val;
                    match(Id);
                    free(name);
                }
            }
            
            // 添加变量到全局作用域
            Scope* current_var_scope = current_scope(scope_stack);
            add_symbol(current_var_scope, name, var_info);
        }
        
        free(name); // 释放临时字符串

        if (token == ',') {
            match(',');
        }
    }
    
    next();
}

void program() {
    parse_program();
}

void parse_program() {
    // 初始化作用域栈和全局作用域，如果尚未初始化
    if (scope_stack == NULL) {
        printf("fatal error: 必须在init_parser中先创建全局作用域\n");
        exit(-1);
    }
    
    // get next token
    next();
    while (token > 0) {
        global_declaration();
    }
}

void init_parser() {
    basetype = INT;
    expr_type = INT;
}

// 清理解析器资源
void cleanup_parser() {
    if (current_func_name) {
        free(current_func_name);
        current_func_name = NULL;
    }
    
    if (scope_stack) {
        free_scope_stack(scope_stack);
        scope_stack = NULL;
    }
}